* Copyright (c) 2005 Intel Corperation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*/
+
#include <xen/config.h>
#include <xen/types.h>
#include <xen/mm.h>
#include <asm/hvm/support.h>
#include <asm/current.h>
+#define hw_error(x) ((void)0)
+
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
{
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
/* XXX: should not export it, but it is needed for an APIC kludge */
-void pic_update_irq(struct hvm_virpic *s)
+void pic_update_irq(struct vpic *vpic)
{
int irq2, irq;
- ASSERT(spin_is_locked(&s->lock));
+ ASSERT(spin_is_locked(&vpic->lock));
/* first look at slave pic */
- irq2 = pic_get_irq(&s->pics[1]);
+ irq2 = pic_get_irq(&vpic->pics[1]);
if (irq2 >= 0) {
/* if irq request by slave pic, signal master PIC */
- pic_set_irq1(&s->pics[0], 2, 1);
- pic_set_irq1(&s->pics[0], 2, 0);
+ pic_set_irq1(&vpic->pics[0], 2, 1);
+ pic_set_irq1(&vpic->pics[0], 2, 0);
}
/* look at requested irq */
- irq = pic_get_irq(&s->pics[0]);
+ irq = pic_get_irq(&vpic->pics[0]);
if (irq >= 0) {
- s->irq_request(s->irq_request_opaque, 1);
+ vpic->irq_request(vpic->irq_request_opaque, 1);
}
}
void pic_set_xen_irq(void *opaque, int irq, int level)
{
- struct hvm_virpic *s = opaque;
+ struct vpic *vpic = opaque;
unsigned long flags;
PicState *ps;
- spin_lock_irqsave(&s->lock, flags);
+ spin_lock_irqsave(&vpic->lock, flags);
- hvm_vioapic_set_xen_irq(current->domain, irq, level);
+ vioapic_set_xen_irq(current->domain, irq, level);
/* Set it on the 8259s */
- ps = &s->pics[irq >> 3];
+ ps = &vpic->pics[irq >> 3];
if (!(ps->elcr & (1 << (irq & 7))))
gdprintk(XENLOG_WARNING, "edge-triggered override IRQ?\n");
if (level) {
ps->irr_xen &= ~(1 << (irq & 7));
}
- pic_update_irq(s);
- spin_unlock_irqrestore(&s->lock, flags);
+ pic_update_irq(vpic);
+ spin_unlock_irqrestore(&vpic->lock, flags);
}
-void pic_set_irq(struct hvm_virpic *s, int irq, int level)
+void pic_set_irq(struct vpic *vpic, int irq, int level)
{
unsigned long flags;
if ( irq < 0 )
return;
- spin_lock_irqsave(&s->lock, flags);
- hvm_vioapic_set_irq(container_of(s, struct domain, arch.hvm_domain.vpic),
- irq, level);
+ spin_lock_irqsave(&vpic->lock, flags);
+ vioapic_set_irq(vpic_domain(vpic), irq, level);
if ( irq < 16 )
{
- pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
- pic_update_irq(s);
+ pic_set_irq1(&vpic->pics[irq >> 3], irq & 7, level);
+ pic_update_irq(vpic);
}
- spin_unlock_irqrestore(&s->lock, flags);
+ spin_unlock_irqrestore(&vpic->lock, flags);
}
/* acknowledge interrupt 'irq' */
s->irr &= ~(1 << irq);
}
-static int pic_read_irq(struct hvm_virpic *s)
+static int pic_read_irq(struct vpic *vpic)
{
int irq, irq2, intno;
unsigned long flags;
- spin_lock_irqsave(&s->lock, flags);
- irq = pic_get_irq(&s->pics[0]);
+ spin_lock_irqsave(&vpic->lock, flags);
+ irq = pic_get_irq(&vpic->pics[0]);
if (irq >= 0) {
- pic_intack(&s->pics[0], irq);
+ pic_intack(&vpic->pics[0], irq);
if (irq == 2) {
- irq2 = pic_get_irq(&s->pics[1]);
+ irq2 = pic_get_irq(&vpic->pics[1]);
if (irq2 >= 0) {
- pic_intack(&s->pics[1], irq2);
+ pic_intack(&vpic->pics[1], irq2);
} else {
/* spurious IRQ on slave controller */
gdprintk(XENLOG_WARNING, "Spurious irq on slave i8259.\n");
irq2 = 7;
}
- intno = s->pics[1].irq_base + irq2;
+ intno = vpic->pics[1].irq_base + irq2;
irq = irq2 + 8;
} else {
- intno = s->pics[0].irq_base + irq;
+ intno = vpic->pics[0].irq_base + irq;
}
} else {
/* spurious IRQ on host controller */
irq = 7;
- intno = s->pics[0].irq_base + irq;
+ intno = vpic->pics[0].irq_base + irq;
gdprintk(XENLOG_WARNING, "Spurious irq on master i8259.\n");
}
- pic_update_irq(s);
- spin_unlock_irqrestore(&s->lock, flags);
+ pic_update_irq(vpic);
+ spin_unlock_irqrestore(&vpic->lock, flags);
return intno;
}
s->elcr = 0xff & s->elcr_mask;
}
-void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int),
+void pic_init(struct vpic *vpic, void (*irq_request)(void *, int),
void *irq_request_opaque)
{
unsigned long flags;
- memset(s, 0, sizeof(*s));
- spin_lock_init(&s->lock);
- s->pics[0].pics_state = s;
- s->pics[1].pics_state = s;
- s->pics[0].elcr_mask = 0xf8;
- s->pics[1].elcr_mask = 0xde;
- spin_lock_irqsave(&s->lock, flags);
- pic_init1(0x20, 0x4d0, &s->pics[0]);
- pic_init1(0xa0, 0x4d1, &s->pics[1]);
- spin_unlock_irqrestore(&s->lock, flags);
- s->irq_request = irq_request;
- s->irq_request_opaque = irq_request_opaque;
+ memset(vpic, 0, sizeof(*vpic));
+ spin_lock_init(&vpic->lock);
+ vpic->pics[0].pics_state = vpic;
+ vpic->pics[1].pics_state = vpic;
+ vpic->pics[0].elcr_mask = 0xf8;
+ vpic->pics[1].elcr_mask = 0xde;
+ spin_lock_irqsave(&vpic->lock, flags);
+ pic_init1(0x20, 0x4d0, &vpic->pics[0]);
+ pic_init1(0xa0, 0x4d1, &vpic->pics[1]);
+ spin_unlock_irqrestore(&vpic->lock, flags);
+ vpic->irq_request = irq_request;
+ vpic->irq_request_opaque = irq_request_opaque;
}
static int intercept_pic_io(ioreq_t *p)
{
- struct hvm_virpic *pic;
+ struct vpic *pic;
uint32_t data;
unsigned long flags;
return 1;
}
- pic = ¤t->domain->arch.hvm_domain.vpic;
+ pic = domain_vpic(current->domain);
if ( p->dir == IOREQ_WRITE ) {
if ( p->data_is_ptr )
(void)hvm_copy_from_guest_phys(&data, p->data, p->size);
static int intercept_elcr_io(ioreq_t *p)
{
- struct hvm_virpic *s;
+ struct vpic *vpic;
uint32_t data;
unsigned long flags;
return 1;
}
- s = ¤t->domain->arch.hvm_domain.vpic;
+ vpic = domain_vpic(current->domain);
if ( p->dir == IOREQ_WRITE ) {
if ( p->data_is_ptr )
(void)hvm_copy_from_guest_phys(&data, p->data, p->size);
else
data = p->data;
- spin_lock_irqsave(&s->lock, flags);
- elcr_ioport_write((void*)&s->pics[p->addr&1],
+ spin_lock_irqsave(&vpic->lock, flags);
+ elcr_ioport_write((void*)&vpic->pics[p->addr&1],
(uint32_t) p->addr, (uint32_t)( data & 0xff));
- spin_unlock_irqrestore(&s->lock, flags);
+ spin_unlock_irqrestore(&vpic->lock, flags);
}
else {
data = (u64) elcr_ioport_read(
- (void*)&s->pics[p->addr&1], (uint32_t) p->addr);
+ (void*)&vpic->pics[p->addr&1], (uint32_t) p->addr);
if ( p->data_is_ptr )
(void)hvm_copy_to_guest_phys(p->data, &data, p->size);
else
int cpu_get_pic_interrupt(struct vcpu *v, int *type)
{
int intno;
- struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
+ struct vpic *vpic = domain_vpic(v->domain);
struct hvm_domain *plat = &v->domain->arch.hvm_domain;
if ( !vlapic_accept_pic_intr(v) )
return -1;
/* read the irq from the PIC */
- intno = pic_read_irq(s);
+ intno = pic_read_irq(vpic);
*type = APIC_DM_EXTINT;
return intno;
}
if (pt->irq == 0) { /* Is it pit irq? */
if (type == APIC_DM_EXTINT)
- vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
+ vec = domain_vpic(v->domain)->pics[0].irq_base;
else
- vec =
- v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector;
+ vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
if (irq == vec)
return 1;
if (pt->irq == 8) { /* Or rtc irq? */
if (type == APIC_DM_EXTINT)
- vec = v->domain->arch.hvm_domain.vpic.pics[1].irq_base;
+ vec = domain_vpic(v->domain)->pics[1].irq_base;
else
- vec =
- v->domain->arch.hvm_domain.vioapic.redirtbl[8].RedirForm.vector;
+ vec = domain_vioapic(v->domain)->redirtbl[8].fields.vector;
if (irq == vec)
return is_rtc_periodic_irq(vrtc);
int is_irq_enabled(struct vcpu *v, int irq)
{
- struct hvm_vioapic *vioapic = &v->domain->arch.hvm_domain.vioapic;
- struct hvm_virpic *vpic=&v->domain->arch.hvm_domain.vpic;
+ struct vioapic *vioapic = domain_vioapic(v->domain);
+ struct vpic *vpic = domain_vpic(v->domain);
- if (vioapic->redirtbl[irq].RedirForm.mask == 0)
+ if (vioapic->redirtbl[irq].fields.mask == 0)
return 1;
if ( irq & 8 ) {
/*
-* Copyright (C) 2001 MandrakeSoft S.A.
-*
-* MandrakeSoft S.A.
-* 43, rue d'Aboukir
-* 75002 Paris - France
-* http://www.linux-mandrake.com/
-* http://www.mandrakesoft.com/
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation; either
-* version 2 of the License, or (at your option) any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
-* Yunhong Jiang <yunhong.jiang@intel.com>
-* Ported to xen by using virtual IRQ line.
-*/
+ * Copyright (C) 2001 MandrakeSoft S.A.
+ *
+ * MandrakeSoft S.A.
+ * 43, rue d'Aboukir
+ * 75002 Paris - France
+ * http://www.linux-mandrake.com/
+ * http://www.mandrakesoft.com/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Yunhong Jiang <yunhong.jiang@intel.com>
+ * Ported to xen by using virtual IRQ line.
+ */
#include <xen/config.h>
#include <xen/types.h>
#define opt_hvm_debug_level opt_vmx_debug_level
#endif
-static void ioapic_enable(hvm_vioapic_t *s, uint8_t enable)
-{
- if (enable)
- s->flags |= IOAPIC_ENABLE_FLAG;
- else
- s->flags &= ~IOAPIC_ENABLE_FLAG;
-}
-
#ifdef HVM_DOMAIN_SAVE_RESTORE
void ioapic_save(QEMUFile* f, void* opaque)
{
}
#endif
-static unsigned long hvm_vioapic_read_indirect(struct hvm_vioapic *s,
- unsigned long addr,
- unsigned long length)
+static unsigned long vioapic_read_indirect(struct vioapic *vioapic,
+ unsigned long addr,
+ unsigned long length)
{
unsigned long result = 0;
- ASSERT(s);
-
- switch (s->ioregsel) {
- case IOAPIC_REG_VERSION:
- result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16)
- | (IOAPIC_VERSION_ID & 0xff));
- break;
-
-#ifndef __ia64__
- case IOAPIC_REG_APIC_ID:
- result = ((s->id & 0xf) << 24);
+ switch ( vioapic->ioregsel )
+ {
+ case VIOAPIC_REG_VERSION:
+ result = ((((VIOAPIC_NUM_PINS-1) & 0xff) << 16)
+ | (VIOAPIC_VERSION_ID & 0xff));
break;
- case IOAPIC_REG_ARB_ID:
- /* XXX how arb_id used on p4? */
- result = ((s->arb_id & 0xf) << 24);
+#if !VIOAPIC_IS_IOSAPIC
+ case VIOAPIC_REG_APIC_ID:
+ case VIOAPIC_REG_ARB_ID:
+ result = ((vioapic->id & 0xf) << 24);
break;
#endif
default:
- {
- uint32_t redir_index = 0;
- uint64_t redir_content = 0;
-
- redir_index = (s->ioregsel - 0x10) >> 1;
-
- if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
- redir_content = s->redirtbl[redir_index].value;
+ {
+ uint32_t redir_index = (vioapic->ioregsel - 0x10) >> 1;
+ uint64_t redir_content;
- result = (s->ioregsel & 0x1)?
- (redir_content >> 32) & 0xffffffff :
- redir_content & 0xffffffff;
- } else {
- printk("apic_mem_readl:undefined ioregsel %x\n",
- s->ioregsel);
- domain_crash_synchronous();
- }
+ if ( redir_index >= VIOAPIC_NUM_PINS )
+ {
+ gdprintk(XENLOG_WARNING, "apic_mem_readl:undefined ioregsel %x\n",
+ vioapic->ioregsel);
break;
}
- } /* switch */
+
+ redir_content = vioapic->redirtbl[redir_index].bits;
+ result = (vioapic->ioregsel & 0x1)?
+ (redir_content >> 32) & 0xffffffff :
+ redir_content & 0xffffffff;
+ break;
+ }
+ }
return result;
}
-static unsigned long hvm_vioapic_read(struct vcpu *v,
- unsigned long addr,
- unsigned long length)
+static unsigned long vioapic_read(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length)
{
- struct hvm_vioapic *s = &(v->domain->arch.hvm_domain.vioapic);
- uint32_t result = 0;
-
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_read addr %lx\n", addr);
+ struct vioapic *vioapic = domain_vioapic(v->domain);
+ uint32_t result;
- ASSERT(s);
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_read addr %lx\n", addr);
addr &= 0xff;
- switch (addr) {
- case IOAPIC_REG_SELECT:
- result = s->ioregsel;
+ switch ( addr )
+ {
+ case VIOAPIC_REG_SELECT:
+ result = vioapic->ioregsel;
break;
- case IOAPIC_REG_WINDOW:
- result = hvm_vioapic_read_indirect(s, addr, length);
+ case VIOAPIC_REG_WINDOW:
+ result = vioapic_read_indirect(vioapic, addr, length);
break;
default:
- break;
+ result = 0;
+ break;
}
return result;
}
-static void hvm_vioapic_update_imr(struct hvm_vioapic *s, int index)
+static void vioapic_update_imr(struct vioapic *vioapic, int index)
{
- if (s->redirtbl[index].RedirForm.mask)
- set_bit(index, &s->imr);
- else
- clear_bit(index, &s->imr);
+ if ( vioapic->redirtbl[index].fields.mask )
+ set_bit(index, &vioapic->imr);
+ else
+ clear_bit(index, &vioapic->imr);
}
-static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
- unsigned long addr,
- unsigned long length,
- unsigned long val)
+static void vioapic_write_indirect(struct vioapic *vioapic,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long val)
{
- switch (s->ioregsel) {
- case IOAPIC_REG_VERSION:
- printk("hvm_vioapic_write_indirect: version register read only\n");
+ switch ( vioapic->ioregsel )
+ {
+ case VIOAPIC_REG_VERSION:
+ /* Writes are ignored. */
break;
-#ifndef __ia64__
- case IOAPIC_REG_APIC_ID:
- s->id = (val >> 24) & 0xf;
+#if !VIOAPIC_IS_IOSAPIC
+ case VIOAPIC_REG_APIC_ID:
+ vioapic->id = (val >> 24) & 0xf;
break;
- case IOAPIC_REG_ARB_ID:
- s->arb_id = val;
+ case VIOAPIC_REG_ARB_ID:
break;
#endif
default:
- {
- uint32_t redir_index = 0;
-
- redir_index = (s->ioregsel - 0x10) >> 1;
+ {
+ uint32_t redir_index = (vioapic->ioregsel - 0x10) >> 1;
+ uint64_t redir_content;
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_write_indirect "
- "change redir index %x val %lx\n",
- redir_index, val);
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_write_indirect "
+ "change redir index %x val %lx\n",
+ redir_index, val);
- if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
- uint64_t redir_content;
+ if ( redir_index >= VIOAPIC_NUM_PINS )
+ {
+ gdprintk(XENLOG_WARNING, "vioapic_write_indirect "
+ "error register %x\n", vioapic->ioregsel);
+ break;
+ }
- redir_content = s->redirtbl[redir_index].value;
+ redir_content = vioapic->redirtbl[redir_index].bits;
- if (s->ioregsel & 0x1) {
+ if ( vioapic->ioregsel & 0x1 )
+ {
#ifdef IRQ0_SPECIAL_ROUTING
- if ( !redir_warning_done && (redir_index == 0) &&
- ((val >> 24) != 0) ) {
- /*
- * Cannot yet handle delivering PIT interrupts to
- * any VCPU != 0. Needs proper fixing, but for now
- * simply spit a warning that we're going to ignore
- * the target in practice & always deliver to VCPU 0
- */
- printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
- "will be ignored.\n", val >> 24);
- redir_warning_done = 1;
- }
-#endif
- redir_content = (((uint64_t)val & 0xffffffff) << 32) |
- (redir_content & 0xffffffff);
- } else
- redir_content = ((redir_content >> 32) << 32) |
- (val & 0xffffffff);
- s->redirtbl[redir_index].value = redir_content;
- hvm_vioapic_update_imr(s, redir_index);
- } else {
- printk("hvm_vioapic_write_indirect "
- "error register %x\n", s->ioregsel);
+ if ( !redir_warning_done && (redir_index == 0) &&
+ ((val >> 24) != 0) )
+ {
+ /*
+ * Cannot yet handle delivering PIT interrupts to any VCPU !=
+ * 0. Needs proper fixing, but for now simply spit a warning
+ * that we're going to ignore the target in practice and always
+ * deliver to VCPU 0.
+ */
+ printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
+ "will be ignored.\n", val >> 24);
+ redir_warning_done = 1;
}
- break;
+#endif
+ redir_content = (((uint64_t)val & 0xffffffff) << 32) |
+ (redir_content & 0xffffffff);
}
+ else
+ {
+ redir_content = ((redir_content >> 32) << 32) |
+ (val & 0xffffffff);
+ }
+ vioapic->redirtbl[redir_index].bits = redir_content;
+ vioapic_update_imr(vioapic, redir_index);
+ break;
+ }
} /* switch */
}
-static void hvm_vioapic_write(struct vcpu *v,
- unsigned long addr,
- unsigned long length,
- unsigned long val)
+static void vioapic_write(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long val)
{
- hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
-
- ASSERT(s);
+ struct vioapic *vioapic = domain_vioapic(v->domain);
addr &= 0xff;
- switch (addr) {
- case IOAPIC_REG_SELECT:
- s->ioregsel = val;
+ switch ( addr )
+ {
+ case VIOAPIC_REG_SELECT:
+ vioapic->ioregsel = val;
break;
- case IOAPIC_REG_WINDOW:
- hvm_vioapic_write_indirect(s, addr, length, val);
+ case VIOAPIC_REG_WINDOW:
+ vioapic_write_indirect(vioapic, addr, length, val);
break;
-#ifdef __ia64__
- case IOAPIC_REG_EOI:
- ioapic_update_EOI(v->domain, val);
+#if VIOAPIC_IS_IOSAPIC
+ case VIOAPIC_REG_EOI:
+ vioapic_update_EOI(v->domain, val);
break;
#endif
}
}
-static int hvm_vioapic_range(struct vcpu *v, unsigned long addr)
+static int vioapic_range(struct vcpu *v, unsigned long addr)
{
- hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
+ struct vioapic *vioapic = domain_vioapic(v->domain);
- if ((s->flags & IOAPIC_ENABLE_FLAG) &&
- (addr >= s->base_address &&
- (addr < s->base_address + IOAPIC_MEM_LENGTH)))
- return 1;
- else
- return 0;
+ return ((addr >= vioapic->base_address &&
+ (addr < vioapic->base_address + VIOAPIC_MEM_LENGTH)));
}
struct hvm_mmio_handler vioapic_mmio_handler = {
- .check_handler = hvm_vioapic_range,
- .read_handler = hvm_vioapic_read,
- .write_handler = hvm_vioapic_write
+ .check_handler = vioapic_range,
+ .read_handler = vioapic_read,
+ .write_handler = vioapic_write
};
-static void hvm_vioapic_reset(hvm_vioapic_t *s)
+static void vioapic_reset(struct vioapic *vioapic)
{
int i;
- memset(s, 0, sizeof(hvm_vioapic_t));
+ memset(vioapic, 0, sizeof(*vioapic));
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- s->redirtbl[i].RedirForm.mask = 0x1;
- hvm_vioapic_update_imr(s, i);
+ for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
+ {
+ vioapic->redirtbl[i].fields.mask = 0x1;
+ vioapic_update_imr(vioapic, i);
}
}
-static void ioapic_update_config(hvm_vioapic_t *s,
- unsigned long address,
- uint8_t enable)
-{
- ASSERT(s);
-
- ioapic_enable(s, enable);
-
- if (address != s->base_address)
- s->base_address = address;
-}
-
-static int ioapic_inj_irq(hvm_vioapic_t *s,
+static int ioapic_inj_irq(struct vioapic *vioapic,
struct vlapic * target,
uint8_t vector,
uint8_t trig_mode,
{
int result = 0;
- ASSERT(s && target);
-
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
- "irq %d trig %d delive mode %d\n",
- vector, trig_mode, delivery_mode);
+ "irq %d trig %d delive mode %d\n",
+ vector, trig_mode, delivery_mode);
- switch (delivery_mode) {
+ switch ( delivery_mode )
+ {
case dest_Fixed:
case dest_LowestPrio:
- if (vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1))
- printk("<ioapic_inj_irq> level interrupt happen before cleared\n");
+ if ( vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1) )
+ gdprintk(XENLOG_WARNING, "level interrupt before cleared\n");
result = 1;
break;
default:
- printk("<ioapic_inj_irq> error delivery mode %d\n",
- delivery_mode);
+ gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
break;
- }
+ }
- return result;
+ return result;
}
#ifndef __ia64__
-static int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint8_t dest)
+static int ioapic_match_logical_addr(
+ struct vioapic *vioapic, int number, uint8_t dest)
{
int result = 0;
- uint32_t logical_dest = vlapic_get_reg(s->lapic_info[number], APIC_LDR);
-
- ASSERT(s && s->lapic_info[number]);
+ uint32_t logical_dest;
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_match_logical_addr "
- "number %i dest %x\n",
- number, dest);
+ "number %i dest %x\n",
+ number, dest);
+
+ logical_dest = vlapic_get_reg(vioapic->lapic_info[number], APIC_LDR);
- switch (vlapic_get_reg(s->lapic_info[number], APIC_DFR))
+ switch ( vlapic_get_reg(vioapic->lapic_info[number], APIC_DFR) )
{
case APIC_DFR_FLAT:
- result =
- (dest & GET_APIC_LOGICAL_ID(logical_dest)) != 0;
+ result = ((dest & GET_APIC_LOGICAL_ID(logical_dest)) != 0);
break;
case APIC_DFR_CLUSTER:
/* Should we support flat cluster mode ?*/
if ( (GET_APIC_LOGICAL_ID(logical_dest) >> 4
- == ((dest >> 0x4) & 0xf)) &&
+ == ((dest >> 0x4) & 0xf)) &&
(logical_dest & (dest & 0xf)) )
result = 1;
break;
default:
- printk("error DFR value for %x local apic\n", number);
+ gdprintk(XENLOG_WARNING, "error DFR value for %x lapic\n", number);
break;
}
return result;
}
#else
-extern int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint8_t dest);
+extern int ioapic_match_logical_addr(
+ struct vioapic *vioapic, int number, uint8_t dest);
#endif
-static uint32_t ioapic_get_delivery_bitmask(hvm_vioapic_t *s,
+static uint32_t ioapic_get_delivery_bitmask(struct vioapic *vioapic,
uint16_t dest,
uint8_t dest_mode,
uint8_t vector,
int i;
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
- "dest %d dest_mode %d "
- "vector %d del_mode %d, lapic_count %d\n",
- dest, dest_mode, vector, delivery_mode, s->lapic_count);
-
- ASSERT(s);
+ "dest %d dest_mode %d "
+ "vector %d del_mode %d, lapic_count %d\n",
+ dest, dest_mode, vector, delivery_mode, vioapic->lapic_count);
if ( dest_mode == 0 )
{
/* Physical mode. */
- for ( i = 0; i < s->lapic_count; i++ )
+ for ( i = 0; i < vioapic->lapic_count; i++ )
{
- if ( VLAPIC_ID(s->lapic_info[i]) == dest )
+ if ( VLAPIC_ID(vioapic->lapic_info[i]) == dest )
{
mask = 1 << i;
break;
/* Broadcast. */
if ( dest == 0xFF )
{
- for ( i = 0; i < s->lapic_count; i++ )
+ for ( i = 0; i < vioapic->lapic_count; i++ )
mask |= ( 1 << i );
}
}
/* Logical destination. Call match_logical_addr for each APIC. */
if ( dest != 0 )
{
- for ( i = 0; i < s->lapic_count; i++ )
+ for ( i = 0; i < vioapic->lapic_count; i++ )
{
- if ( s->lapic_info[i] &&
- ioapic_match_logical_addr(s, i, dest) )
+ if ( vioapic->lapic_info[i] &&
+ ioapic_match_logical_addr(vioapic, i, dest) )
mask |= (1<<i);
}
}
}
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
- "mask %x\n", mask);
+ "mask %x\n", mask);
return mask;
}
-static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
+static void ioapic_deliver(struct vioapic *vioapic, int irq)
{
- uint16_t dest = s->redirtbl[irqno].RedirForm.dest_id;
- uint8_t dest_mode = s->redirtbl[irqno].RedirForm.destmode;
- uint8_t delivery_mode = s->redirtbl[irqno].RedirForm.deliver_mode;
- uint8_t vector = s->redirtbl[irqno].RedirForm.vector;
- uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
+ uint16_t dest = vioapic->redirtbl[irq].fields.dest_id;
+ uint8_t dest_mode = vioapic->redirtbl[irq].fields.dest_mode;
+ uint8_t delivery_mode = vioapic->redirtbl[irq].fields.delivery_mode;
+ uint8_t vector = vioapic->redirtbl[irq].fields.vector;
+ uint8_t trig_mode = vioapic->redirtbl[irq].fields.trig_mode;
uint32_t deliver_bitmask;
struct vlapic *target;
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
- "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
- dest, dest_mode, delivery_mode, vector, trig_mode);
+ "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
+ dest, dest_mode, delivery_mode, vector, trig_mode);
deliver_bitmask = ioapic_get_delivery_bitmask(
- s, dest, dest_mode, vector, delivery_mode);
-
- if (!deliver_bitmask) {
+ vioapic, dest, dest_mode, vector, delivery_mode);
+ if ( !deliver_bitmask )
+ {
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
- "no target on destination\n");
-
+ "no target on destination\n");
return;
}
- switch (delivery_mode) {
+ switch ( delivery_mode )
+ {
case dest_LowestPrio:
{
#ifdef IRQ0_SPECIAL_ROUTING
/* Force round-robin to pick VCPU 0 */
- if (irqno == 0)
- target = s->lapic_info[0];
+ if ( irq == 0 )
+ target = vioapic->lapic_info[0];
else
#endif
- target = apic_round_robin(s->domain, dest_mode,
+ target = apic_round_robin(vioapic_domain(vioapic), dest_mode,
vector, deliver_bitmask);
- if (target) {
- ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
+ if ( target != NULL )
+ {
+ ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode);
vcpu_kick(vlapic_vcpu(target));
- } else
+ }
+ else
+ {
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
- "null round robin mask %x vector %x delivery_mode %x\n",
- deliver_bitmask, vector, dest_LowestPrio);
+ "null round robin mask %x vector %x delivery_mode %x\n",
+ deliver_bitmask, vector, dest_LowestPrio);
+ }
break;
}
case dest_ExtINT:
{
uint8_t bit;
- for (bit = 0; bit < s->lapic_count; bit++) {
+ for ( bit = 0; bit < vioapic->lapic_count; bit++ )
+ {
if ( !(deliver_bitmask & (1 << bit)) )
continue;
#ifdef IRQ0_SPECIAL_ROUTING
/* Do not deliver timer interrupts to VCPU != 0 */
- if ( (irqno == 0) && (bit !=0 ) )
- target = s->lapic_info[0];
+ if ( (irq == 0) && (bit != 0) )
+ target = vioapic->lapic_info[0];
else
#endif
- target = s->lapic_info[bit];
- if (target) {
- ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
+ target = vioapic->lapic_info[bit];
+ if ( target != NULL )
+ {
+ ioapic_inj_irq(vioapic, target, vector,
+ trig_mode, delivery_mode);
vcpu_kick(vlapic_vcpu(target));
}
}
case dest_INIT:
case dest__reserved_2:
default:
- printk("Not support delivey mode %d\n", delivery_mode);
+ gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
+ delivery_mode);
break;
}
}
-static int ioapic_get_highest_irq(hvm_vioapic_t *s)
+static int ioapic_get_highest_irq(struct vioapic *vioapic)
{
- uint32_t irqs = (s->irr | s->irr_xen) & ~s->isr & ~s->imr;
+ uint32_t irqs = vioapic->irr | vioapic->irr_xen;
+ irqs &= ~vioapic->isr & ~vioapic->imr;
return fls(irqs) - 1;
}
-static void service_ioapic(hvm_vioapic_t *s)
+static void service_ioapic(struct vioapic *vioapic)
{
- int irqno;
+ int irq;
- while ((irqno = ioapic_get_highest_irq(s)) != -1) {
+ while ( (irq = ioapic_get_highest_irq(vioapic)) != -1 )
+ {
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic highest irq %x\n", irq);
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic "
- "highest irqno %x\n", irqno);
+ if ( !test_bit(irq, &vioapic->imr) )
+ ioapic_deliver(vioapic, irq);
- if (!test_bit(irqno, &s->imr)) {
- ioapic_deliver(s, irqno);
- }
+ if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_LEVEL_TRIG )
+ vioapic->isr |= (1 << irq);
- if (s->redirtbl[irqno].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER) {
- s->isr |= (1 << irqno);
- }
-
- s->irr &= ~(1 << irqno);
- s->irr_xen &= ~(1 << irqno);
+ vioapic->irr &= ~(1 << irq);
+ vioapic->irr_xen &= ~(1 << irq);
}
}
-void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level)
+void vioapic_set_xen_irq(struct domain *d, int irq, int level)
{
- hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic;
+ struct vioapic *vioapic = domain_vioapic(d);
- if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask)
+ if ( vioapic->redirtbl[irq].fields.mask )
return;
- if (s->redirtbl[irq].RedirForm.trigmod != IOAPIC_LEVEL_TRIGGER)
- gdprintk(XENLOG_WARNING, "Forcing edge triggered APIC irq %d?\n", irq);
+ if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_EDGE_TRIG )
+ gdprintk(XENLOG_WARNING, "Forcing edge triggered APIC irq %d?\n", irq);
- if (level)
- s->irr_xen |= 1 << irq;
+ if ( level )
+ vioapic->irr_xen |= 1 << irq;
else
- s->irr_xen &= ~(1 << irq);
+ vioapic->irr_xen &= ~(1 << irq);
}
-void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
+void vioapic_set_irq(struct domain *d, int irq, int level)
{
- hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
+ struct vioapic *vioapic = domain_vioapic(d);
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq "
- "irq %x level %x\n", irq, level);
+ "irq %x level %x\n", irq, level);
- if ( (irq < 0) || (irq >= IOAPIC_NUM_PINS) )
+ if ( (irq < 0) || (irq >= VIOAPIC_NUM_PINS) )
return;
- if ( !IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask )
+ if ( vioapic->redirtbl[irq].fields.mask )
return;
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_set_irq entry %x "
- "vector %x deliver_mod %x destmode %x delivestatus %x "
- "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n",
- irq,
- s->redirtbl[irq].RedirForm.vector,
- s->redirtbl[irq].RedirForm.deliver_mode,
- s->redirtbl[irq].RedirForm.destmode,
- s->redirtbl[irq].RedirForm.delivestatus,
- s->redirtbl[irq].RedirForm.polarity,
- s->redirtbl[irq].RedirForm.remoteirr,
- s->redirtbl[irq].RedirForm.trigmod,
- s->redirtbl[irq].RedirForm.mask,
- s->redirtbl[irq].RedirForm.dest_id);
-
- if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_set_irq entry %x "
+ "vector %x delivery_mode %x dest_mode %x delivery_status %x "
+ "polarity %x remote_irr %x trig_mode %x mask %x dest_id %x\n",
+ irq,
+ vioapic->redirtbl[irq].fields.vector,
+ vioapic->redirtbl[irq].fields.delivery_mode,
+ vioapic->redirtbl[irq].fields.dest_mode,
+ vioapic->redirtbl[irq].fields.delivery_status,
+ vioapic->redirtbl[irq].fields.polarity,
+ vioapic->redirtbl[irq].fields.remote_irr,
+ vioapic->redirtbl[irq].fields.trig_mode,
+ vioapic->redirtbl[irq].fields.mask,
+ vioapic->redirtbl[irq].fields.dest_id);
+
+ if ( (irq >= 0) && (irq < VIOAPIC_NUM_PINS) )
+ {
uint32_t bit = 1 << irq;
- if (s->redirtbl[irq].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER) {
- if (level)
- s->irr |= bit;
+ if ( vioapic->redirtbl[irq].fields.trig_mode == VIOAPIC_LEVEL_TRIG )
+ {
+ if ( level )
+ vioapic->irr |= bit;
else
- s->irr &= ~bit;
- } else {
- if (level)
+ vioapic->irr &= ~bit;
+ }
+ else
+ {
+ if ( level )
/* XXX No irr clear for edge interrupt */
- s->irr |= bit;
+ vioapic->irr |= bit;
}
}
- service_ioapic(s);
+ service_ioapic(vioapic);
}
/* XXX If level interrupt, use vector->irq table for performance */
-static int get_redir_num(hvm_vioapic_t *s, int vector)
+static int get_redir_num(struct vioapic *vioapic, int vector)
{
- int i = 0;
-
- ASSERT(s);
+ int i;
- for(i = 0; i < IOAPIC_NUM_PINS; i++) {
- if (s->redirtbl[i].RedirForm.vector == vector)
+ for ( i = 0; i < VIOAPIC_NUM_PINS; i++ )
+ if ( vioapic->redirtbl[i].fields.vector == vector )
return i;
- }
return -1;
}
-void ioapic_update_EOI(struct domain *d, int vector)
+void vioapic_update_EOI(struct domain *d, int vector)
{
- hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
+ struct vioapic *vioapic = domain_vioapic(d);
int redir_num;
- if ((redir_num = get_redir_num(s, vector)) == -1) {
- printk("Can't find redir item for %d EOI \n", vector);
+ if ( (redir_num = get_redir_num(vioapic, vector)) == -1 )
+ {
+ gdprintk(XENLOG_WARNING, "Can't find redir item for %d EOI\n", vector);
return;
}
- if (!test_and_clear_bit(redir_num, &s->isr)) {
- printk("redir %d not set for %d EOI\n", redir_num, vector);
+ if ( !test_and_clear_bit(redir_num, &vioapic->isr) )
+ {
+ gdprintk(XENLOG_WARNING, "redir %d not set for %d EOI\n",
+ redir_num, vector);
return;
}
}
-int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
+int vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
{
- hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
+ struct vioapic *vioapic = domain_vioapic(v->domain);
- if (v->vcpu_id != s->lapic_count) {
- printk("hvm_vioapic_add_lapic "
- "cpu_id not match vcpu_id %x lapic_count %x\n",
- v->vcpu_id, s->lapic_count);
+ if ( v->vcpu_id != vioapic->lapic_count )
+ {
+ gdprintk(XENLOG_ERR, "vioapic_add_lapic "
+ "cpu_id not match vcpu_id %x lapic_count %x\n",
+ v->vcpu_id, vioapic->lapic_count);
domain_crash_synchronous();
}
- /* update count later for race condition on interrupt */
- s->lapic_info[s->lapic_count] = vlapic;
- s->lapic_count ++;
+ /* Update count later for race condition on interrupt. */
+ vioapic->lapic_info[vioapic->lapic_count] = vlapic;
+ wmb();
+ vioapic->lapic_count++;
- return s->lapic_count;
+ return vioapic->lapic_count;
}
-hvm_vioapic_t * hvm_vioapic_init(struct domain *d)
+void vioapic_init(struct domain *d)
{
- int i = 0;
- hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
-
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_init\n");
-
- hvm_vioapic_reset(s);
-
- s->domain = d;
+ struct vioapic *vioapic = domain_vioapic(d);
- for (i = 0; i < MAX_LAPIC_NUM; i++)
- s->lapic_info[i] = NULL;
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_init\n");
- /* Remove after GFW ready */
- ioapic_update_config(s, IOAPIC_DEFAULT_BASE_ADDRESS, 1);
+ vioapic_reset(vioapic);
- return s;
+ vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS;
}